package com.funny.encrypt.interceptor;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.funny.encrypt.anno.DuyanSensitive;
import com.funny.encrypt.anno.NeedEncrypt;
import com.funny.encrypt.anno.ParamEncrypt;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.util.Objects;
import java.util.Properties;

/**
 * @author fanxiao  2022/1/17
 * @since 1.0.0
 */
@Slf4j
@Intercepts({
		@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
		@Signature(type = ParameterHandler.class, method = "setParameters", args = PreparedStatement.class),
})
public class ParameterEncryptInterceptor implements Interceptor {

	private static final String KEY = "HelloWorldQQQQQQ";

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		log.info("自定义拦截器...");
		if (Executor.class.isAssignableFrom(invocation.getTarget().getClass())) {
			log.info("现在是Executor处理");
			Object[] args = invocation.getArgs();
			MappedStatement mappedStatement = (MappedStatement) args[0];
			String id = mappedStatement.getId();
			log.info("id:{}", id);
		}
		if (ParameterHandler.class.isAssignableFrom(invocation.getTarget().getClass())) {
			log.info("现在是ParameterHandler处理");
			ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();

//		Field parameterField = parameterHandler.getClass().getDeclaredField("parameterObject");
//		parameterField.setAccessible(true);
//		Object parameterObject = parameterField.get(parameterHandler);

			// 获取参数对像，即 mapper 中 paramsType 的实例
			Object parameterObject = parameterHandler.getParameterObject();
			if(parameterObject instanceof MapperMethod.ParamMap) {

			}
			if (parameterObject != null) {
				Class<?> parameterObjectClass = parameterObject.getClass();

				DuyanSensitive annotation = AnnotationUtils.findAnnotation(parameterObjectClass, DuyanSensitive.class);
				if (Objects.nonNull(annotation)) {
					Field[] declaredFields = parameterObjectClass.getDeclaredFields();
					needEncrypt(declaredFields, parameterObject);
				}
			}
		}

		return invocation.proceed();
	}

	private void needEncrypt(Field[] fields, Object paramsObject) throws IllegalAccessException {
		SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, KEY.getBytes());
		for (Field field : fields) {
		  NeedEncrypt annotation = field.getAnnotation(NeedEncrypt.class);
		  if (!Objects.isNull(annotation)) {
			field.setAccessible(true);
			Object object = field.get(paramsObject);
			if (object instanceof String) {
			  String value = (String) object;
			  field.set(paramsObject, aes.encryptHex(value));
			}
		  }
		}
	}

	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {

	}
}